package kata.chop;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import org.junit.Before;
import org.junit.Test;

public abstract class BinaryChopTest {

	private BinaryChop binaryChop;

	@Before
	public void before() {
		binaryChop = createBinaryChop();
	}

	protected abstract BinaryChop createBinaryChop();

	@Test
	public void notFoundForEmptyArray() throws Exception {
		assertThat(binaryChop.chop(3, array()), equalTo(-1));
	}

	@Test
	public void notFoundInOneElementArray() throws Exception {
		assertThat(binaryChop.chop(3, array(1)), equalTo(-1));
	}

	@Test
	public void foundOnFirstPositionInOneElementArray() throws Exception {
		assertThat(binaryChop.chop(1, array(1)), equalTo(0));
	}

	@Test
	public void foundOnFirstPositionInThreeElementArray() throws Exception {
		assertThat(binaryChop.chop(1, array(1, 3, 5)), equalTo(0));
	}

	@Test
	public void foundOnSecondPositionInThreeElementArray() throws Exception {
		assertThat(binaryChop.chop(3, array(1, 3, 5)), equalTo(1));
	}

	@Test
	public void foundOnThirdPositionInThreeElementArray() throws Exception {
		assertThat(binaryChop.chop(5, array(1, 3, 5)), equalTo(2));
	}

	@Test
	public void notFoundInThreeElementArray() throws Exception {
		assertThat(binaryChop.chop(0, array(1, 3, 5)), equalTo(-1));
		assertThat(binaryChop.chop(2, array(1, 3, 5)), equalTo(-1));
		assertThat(binaryChop.chop(4, array(1, 3, 5)), equalTo(-1));
		assertThat(binaryChop.chop(6, array(1, 3, 5)), equalTo(-1));
	}

	@Test
	public void foundInFourElementArray() throws Exception {
		assertThat(binaryChop.chop(1, array(1, 3, 5, 7)), equalTo(0));
		assertThat(binaryChop.chop(3, array(1, 3, 5, 7)), equalTo(1));
		assertThat(binaryChop.chop(5, array(1, 3, 5, 7)), equalTo(2));
		assertThat(binaryChop.chop(7, array(1, 3, 5, 7)), equalTo(3));
	}

	@Test
	public void notFoundInFourElementArray() throws Exception {
		assertThat(binaryChop.chop(0, array(1, 3, 5, 7)), equalTo(-1));
		assertThat(binaryChop.chop(2, array(1, 3, 5, 7)), equalTo(-1));
		assertThat(binaryChop.chop(4, array(1, 3, 5, 7)), equalTo(-1));
		assertThat(binaryChop.chop(6, array(1, 3, 5, 7)), equalTo(-1));
		assertThat(binaryChop.chop(8, array(1, 3, 5, 7)), equalTo(-1));
	}

	@Test
	public void bigTest() throws Exception {
		assertThat(binaryChop.chop(5,
				array(1, 3, 5, 7, 10, 15, 22, 35, 68, 99, 100, 158, 196)),
				equalTo(2));

		assertThat(binaryChop.chop(196,
				array(1, 3, 5, 7, 10, 15, 22, 35, 68, 99, 100, 158, 196)),
				equalTo(12));
	}

	private int[] array(int... elements) {
		return elements;
	}

}
